package jfprincesstests.structures.negotiation;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import jfprincesstests.fakes.FakeActivationCmd;
import jfprincesstests.fakes.FakeActivator;
import jfprincesstests.fakes.FakeCmd;
import jfprincesstests.fakes.FakeCondition;
import jfuzzyprincepless.algorithm.structure.*;
import jfuzzyprincepless.zarchive.algorithm.structure.ICommandConstruction;
import jfuzzyprincepless.zarchive.algorithm.structure.ifcnstr.*;
import jfuzzyprincepless.negotiation.DefaultNegotiationContext;
import jfuzzyprincepless.zarchive.negotiation.IAgentsExporter;
import jfuzzyprincepless.zarchive.negotiation.protocols.propositionnetwork.ExecuteIfNegotiation;
import jfuzzyprincepless.zarchive.negotiation.protocols.propositionnetwork.DefaultExecIfProtocol;
import jfuzzyprincepless.zarchive.negotiation.protocols.INegotiationProtocol__Q_del;
import jfuzzyprincepless.negotiation.INegotiation;
import laboratoryQ.junit.ignore.patch.BaseTestCase;

public class TestIfConstruction extends BaseTestCase {
	public void testIExecuteIfNegotiation() {
		INegotiationCondition condition =
			new NegotiationAndCondition();
		List<ICommandConstruction> thenCommands =
			new ArrayList<ICommandConstruction>();
		List<ICommandConstruction> elseCommands =
			new ArrayList<ICommandConstruction>();
		NegotiationIfConstruction ifConstruction =
			new NegotiationIfConstruction(
				condition,
				thenCommands,
				elseCommands
			);
		assertIsInstance(ifConstruction, IConstruction.class);
		IExecuteIfNegotiation neg = new ExecuteIfNegotiation(
			ifConstruction
		);

		assertSame(
			condition,
			neg.getIfConstruction().getCondition()
		);
		assertSame(
			thenCommands,
			neg.getIfConstruction().getThenCommands()
		);
		assertSame(
			elseCommands,
			neg.getIfConstruction().getElseCommands()
		);
	}

	public void testIFConstructionInit() {
		INegotiationCondition condition =
			new FakeCondition(0.1);
		List<ICommandConstruction> thenCommands =
			Arrays.<ICommandConstruction>asList(
				new FakeActivator(null)
			);
		List<ICommandConstruction> elseCommands =
			new ArrayList<ICommandConstruction>();

		NegotiationIfConstruction ifConstruction =
			new NegotiationIfConstruction(
				condition,
				thenCommands,
				elseCommands
			);
		assertEquals(
			0,
			ifConstruction.getAgents().size()
		);

		ifConstruction.extractAgentsFromConstructions();
		assertEquals(
			2,
			ifConstruction.getAgents().size()
		);
	}

	public void testIfNegotiationProtocol() {
		INegotiationProtocol__Q_del protocol =
			new DefaultExecIfProtocol();

		NegotiationIfConstruction nifConstr =
			new NegotiationIfConstruction();

		nifConstr.extractAgentsFromConstructions();
		INegotiation negotiation =
			protocol.createNegotiation(nifConstr, null);
		assertIsInstance(negotiation, ExecuteIfNegotiation.class);
	}

	public void testAgentsNegotiationIfStructure() {
		StringBuilder sb = new StringBuilder();

		// ### ### ### init ### ### ###

		FakeCondition fakeCondition = new FakeCondition(0.9);
		INegotiationCondition icondition = fakeCondition;

		ICommandConstruction cmdTrue =
			new FakeActivationCmd(new FakeCmd(sb, "True"));
		ICommandConstruction cmdFalse =
			new FakeActivationCmd(new FakeCmd(sb, "False"));

		NegotiationIfConstruction nifStruct =
			new NegotiationIfConstruction(
				icondition,
				Arrays.<ICommandConstruction>asList(cmdTrue),
				Arrays.<ICommandConstruction>asList(cmdFalse)
			);
		nifStruct.extractAgentsFromConstructions();

		// ### ### ### run  ### ### ###
		ICommandConstruction ifcmd = nifStruct;

		ifcmd.execute(new DefaultNegotiationContext());
		assertEquals("True;", sb.toString());

		fakeCondition.setTruthDegree(0.1);
		sb.setLength(0);
		ifcmd.execute(new DefaultNegotiationContext());
		assertEquals("False;", sb.toString());
	}

	/**
	 * 	IF (b0 AND b1 AND b2) THEN
	 * 		tact0()
	 * 		tact1()
	 * 		tact2()
	 * 	ELSE
	 * 		fact0()
	 *
	 * see {@link jfprincesstests.structures.negotiation
	 * .TestIfNegotiationProtocol#testInvestmentNegotiation()}
	 */
	public void testExecuteIfCommands() {
		StringBuilder sb = new StringBuilder();

		INegotiationCondition existsPercpectiveInvestment =
			new FakeCondition(0.9);
		INegotiationCondition cacheIsNotAsMuchAsWant =
			new FakeCondition(0.6);
		INegotiationCondition existNotNecessaryGoods =
			new FakeCondition(0.1);
		INegotiationCondition andCondition =
			new NegotiationAndCondition(
				existsPercpectiveInvestment,
				cacheIsNotAsMuchAsWant,
				existNotNecessaryGoods
			);

		IIfConstruction ifstruct =
			new NegotiationIfConstruction(
				andCondition,
				Arrays.<ICommandConstruction>asList(
					new FakeCmd(sb, "Invest0()"),
					new FakeCmd(sb, "Invest1()"),
					new FakeCmd(sb, "Invest2()")
				),
				Arrays.<ICommandConstruction>asList(
					new FakeCmd(sb, "MakeReport")
				)
			);

		// ### ### ### ### RUN ### ### ### ### ### ### ###

		ifstruct.execute(new DefaultNegotiationContext());
		assertEquals(
			"Invest0();Invest1();Invest2();" +
			"MakeReport;",
			sb.toString()
		);
	}

	public void testExportAgentsFromIf() {
		NegotiationIfConstruction nifConstr =
			new NegotiationIfConstruction(
				new FakeCondition(0.1),
				Arrays.<ICommandConstruction>asList(
					new FakeActivator(new FakeActivationCmd(new FakeCmd(null, null)))
				),
				Arrays.<ICommandConstruction>asList(
					new FakeActivator(new FakeActivationCmd(new FakeCmd(null, null)))
				)
			);
		assertIsInstance(nifConstr, IAgentsExporter.class);
		IAgentsExporter eaConstr = nifConstr;
		assertEquals(0, eaConstr.getAgents().size());

		nifConstr.extractAgentsFromConstructions();
		assertEquals(3, eaConstr.getAgents().size());
	}
}
